package com.gitee.huanminabc.jlambda_sql.segments;


import com.gitee.huanminabc.jlambda_sql.SQL;
import com.gitee.huanminabc.jlambda_sql.base.SqlFun;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 函数实现类
 * @param <T>
 * @param <Children>
 */
public abstract class SqlFunImplSegments<T, Children extends SqlRelationImplSegments<T, Children>>    extends SqlRelationImplSegments<T, Children> implements SqlFunSegments<Children> {
    public SqlFunImplSegments() {
    }
    public SqlFunImplSegments(Class<T> entityClass, SQL sql) {
        super(entityClass, sql);
    }

    @Override
    public Children SUM(String sql) {
        SQL().addSelectColumn("SUM("+sql+")");
        return typedThis;
    }

    public Children SUM(String sql, String alias) {
        SQL().addSelectColumnAlias("SUM("+sql+")",alias);
        return typedThis;
    }
    @Override
    public <Y> Children SUM(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("SUM(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",sqlColumn.getColumnName()));
        return typedThis;
    }

    /**
     * 可以在函数中嵌套条件表达式,来完成过滤统计
     * @param sql
     * @return
     */

    @Override
    public Children SUM_REDUCE(SqlFun<Children,Children> sql){
        SUM_REDUCE(sql,null);
        return typedThis;
    }
    @Override
    public <Y> Children SUM_REDUCE(SqlFun<Children,Children> sql, SqlFun<Y, ?> alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();

        if (alias != null) {
            getFunFieldName(alias, sqlColumn -> SQL().addSelectColumn("SUM("+string.trim()+") "+sqlColumn.getColumnName()));
        } else {
            //去掉前后的空格
            SQL().addSelectColumn("SUM("+string.trim()+")");
        }
        return typedThis;
    }



    @Override
    public Children AVG(String sql) {
        SQL().addSelectColumn("AVG("+sql+")");
        return typedThis;
    }
    @Override
    public Children AVG(String sql, String alias){
        SQL().addSelectColumnAlias("AVG("+sql+")",alias);
        return typedThis;
    }
    @Override
    public <Y> Children AVG(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("AVG(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",sqlColumn.getColumnName()));
        return typedThis;
    }


    @Override
    public Children AVG_REDUCE(SqlFun<Children,Children> sql){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumn("AVG("+string.trim()+")");
        return typedThis;
    }
    @Override
    public Children AVG_REDUCE(SqlFun<Children, Children> sql, String alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumnAlias("AVG("+string.trim()+")",alias);
        return typedThis;
    }




    @Override
    public Children MAX(String sql) {
        SQL().addSelectColumn("MAX("+sql+")");
        return typedThis;
    }
    @Override
    public Children MAX(String sql, String alias){
        SQL().addSelectColumnAlias("MAX("+sql+")",alias);
        return typedThis;
    }

    @Override
    public <Y> Children MAX(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("MAX(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",sqlColumn.getColumnName()));
        return typedThis;
    }


    @Override
    public  Children MAX_REDUCE(SqlFun<Children,Children> sql){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumn("MAX("+string.trim()+")");
        return typedThis;
    }
    @Override
    public  Children MAX_REDUCE(SqlFun<Children,Children> sql ,String alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumnAlias("MAX("+string.trim()+")",alias);
        return typedThis;
    }



    @Override
    public Children MIN(String sql) {
        SQL().addSelectColumn("MIN("+sql+")");
        return typedThis;
    }
    @Override
    public Children MIN(String sql, String alias){
        SQL().addSelectColumnAlias("MIN("+sql+")",alias);
        return typedThis;
    }
    @Override
    public <Y> Children MIN(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("MIN(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",sqlColumn.getColumnName()));
        return typedThis;
    }

    @Override
    public  Children MIN_REDUCE(SqlFun<Children,Children> sql){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumn("MIN("+string.trim()+")");
        return typedThis;
    }
    @Override
    public  Children MIN_REDUCE(SqlFun<Children, Children> sql, String alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumnAlias("MIN("+string.trim()+")",alias);
        return typedThis;
    }



    @Override
    public Children COUNT(String sql) {
        SQL().addSelectColumn("COUNT("+sql+")");
        return typedThis;
    }
    @Override
    public Children COUNT(String sql, String alias){
        SQL().addSelectColumnAlias("COUNT("+sql+")",alias);
        return typedThis;
    }

    @Override
    public <Y> Children COUNT(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("COUNT(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",sqlColumn.getColumnName()));
        return typedThis;
    }

    @Override
    public Children COUNT_REDUCE(SqlFun<Children,Children> sql){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumn("COUNT("+string.trim()+")");
        return typedThis;
    }
    @Override
    public Children COUNT_REDUCE(SqlFun<Children, Children> sql, String alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumnAlias("COUNT("+string.trim()+")",alias);
        return typedThis;
    }


    //defaultValue 为数字或者表达式
    @Override
    public <Y> Children IFNULL(SqlFun<Y, ?> column,Object defaultValue){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("IFNULL(",sqlColumn.getTableName(),sqlColumn.getColumnName(),","+ defaultValue +")",sqlColumn.getColumnName()));
        return typedThis;
    }
    @Override
    public <Y> Children IFNULL(SqlFun<Y, ?> column1,SqlFun<Y, ?> column2,String alias){
        AtomicReference<SQL.SqlColumn> sqlColumn1 = new AtomicReference<>();
        AtomicReference<SQL.SqlColumn> sqlColumn2 = new AtomicReference<>();
        getFunFieldName(column1, sqlColumn1::set);
        getFunFieldName(column2, sqlColumn2::set);
        SQL().addSelectColumn("IFNULL(", sqlColumn1.get().getTableName(), sqlColumn1.get().getColumnName(),","+sqlColumn2.get().getTableName() +"."+sqlColumn2.get().getColumnName()+")", alias);
        return typedThis;
    }

    /**
     *
     * @param column  列
     * @param pos  要截取的位置
     * @param len  截取多长
     * @return
     */
    @Override
    public   <Y>  Children  SUBSTR( SqlFun<Y, ?> column,int pos,int len){
        getFunFieldName(column, sqlColumn -> SQL().
                addSelectColumn("SUBSTR(",sqlColumn.getTableName(),sqlColumn.getColumnName(),","+pos+","+len+")",
                        sqlColumn.getColumnName()));
        return typedThis;
    }
    @Override
    public final <Y> Children CONCAT(String alias, SqlFun<Y, ?>... column){
        StringBuilder sb = new StringBuilder();
        for (SqlFun<Y, ?> ySqlFun : column) {
            getFunFieldName(ySqlFun, sqlColumn -> sb.append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(","));
        }
        sb.deleteCharAt(sb.length()-1);
        SQL().addSelectColumnAlias("CONCAT("+sb+")",alias);
        return typedThis;
    }

    @Override
    public Children CONCAT( String alias,String... column){
        StringBuilder sb = new StringBuilder();
        for (String s : column) {
            sb.append(s).append(",");
        }
        sb.deleteCharAt(sb.length()-1);
        SQL().addSelectColumnAlias("CONCAT("+sb+")",alias);
        return typedThis;
    }

    @Override
    public <Y>  Children LENGTH( SqlFun<Y, ?> column,String alias){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn("LENGTH(",sqlColumn.getTableName(),sqlColumn.getColumnName(),")",alias));
        return typedThis;
    }
    @Override
    public Children LENGTH( String column,String alias){
        SQL().addSelectColumnAlias("LENGTH("+column+")",alias);
        return typedThis;
    }

}
